package com.rabbit.videoplayer.tools

import android.content.Context
import android.content.SharedPreferences
import java.io.*
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty

class PreferenceDelegate<T>(val context: Context?, private val propName: String, private val defaultValue: T) : ReadWriteProperty<Any, T> {

    private val sharedPreferences: SharedPreferences? by lazy {
        context?.getSharedPreferences(
            "VideoSP",
            Context.MODE_PRIVATE
        )
    }

    fun clear() {
        sharedPreferences?.edit()?.clear()?.apply()
    }

    /**
     * 根据key删除存储数据
     */
    fun clearPreference(key : String){
        sharedPreferences?.edit()?.remove(key)?.apply()
    }

    /**
     * 序列化对象
     */
    @Throws(IOException::class)
    private fun<A> serialize(obj: A): String {
        val byteArrayOutputStream = ByteArrayOutputStream()
        val objectOutputStream = ObjectOutputStream(
            byteArrayOutputStream)
        objectOutputStream.writeObject(obj)
        var serStr = byteArrayOutputStream.toString("ISO-8859-1")
        serStr = java.net.URLEncoder.encode(serStr, "UTF-8")
        objectOutputStream.close()
        byteArrayOutputStream.close()
        return serStr
    }

    /**
     * 反序列化对象
     * @param str
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    @Suppress("UNCHECKED_CAST")
    @Throws(IOException::class, ClassNotFoundException::class)
    private fun<A> deSerialization(str: String): A {
        val redStr = java.net.URLDecoder.decode(str, "UTF-8")
        val byteArrayInputStream = ByteArrayInputStream(
            redStr.toByteArray(charset("ISO-8859-1")))
        val objectInputStream = ObjectInputStream(
            byteArrayInputStream)
        val obj = objectInputStream.readObject()
        objectInputStream.close()
        byteArrayInputStream.close()
        return obj as A
    }


    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
        value?.let { putSPValue(propName, value) }
    }

    override fun getValue(thisRef: Any, property: KProperty<*>): T {
        return getSPValue(propName, defaultValue) ?: defaultValue
    }

    @Suppress("UNCHECKED_CAST")
    private fun <T> getSPValue(name: String, defaultValue: T): T? = with(sharedPreferences) {
        val result = when (defaultValue) {
            is String -> this?.getString(name, defaultValue)?:""
            is Int -> this?.getInt(name, defaultValue)?:0
            is Long -> this?.getLong(name, defaultValue)?:0L
            is Float -> this?.getFloat(name, defaultValue)?:0f
            is Boolean -> this?.getBoolean(name, defaultValue)?:false
            else -> deSerialization(this?.getString(name,serialize(defaultValue)).toString())
        }
        result as T
    }

    private fun <T> putSPValue(name: String, value: T) = with(sharedPreferences?.edit()) {
        when (value) {
            is Long -> this?.putLong(name, value)
            is String -> this?.putString(name, value)
            is Int -> this?.putInt(name, value)
            is Boolean -> this?.putBoolean(name, value)
            is Float -> this?.putFloat(name, value)
            else -> this?.putString(name,serialize(value))
        }
    }?.apply()
}